#include "LuaAction.h"
#include "luna/luna.h"

namespace LuaFunction
{
	int EmptyFunction(lua_State *L)
	{
		return 0;
	}
	int msg(lua_State *L)
	{
		return 0;
	}
	void ExecutionLimit(lua_State *L, lua_Debug *ar)
	{
		luaL_error(L, "Infinite loop detected");
	}
	int OutputToFile(lua_State *L)
	{
		int argc = lua_gettop(L);
		if(argc == 1)
		{
			if(lua_isstring(L, 1))
			{
				cout << lua_tostring(L, 1) << endl;
			}
		}
		return 0;
	}
}

CLuaAction::CLuaAction(CScriptInteraction *aInfo)
{
	mExecutionInfo = aInfo;
}

CLuaAction::~CLuaAction(void)
{
	//delete mExecutionInfo;
}

bool CLuaAction::PrepareAction()
{
	Engine = luaL_newstate();

	luaopen_base(Engine);
	luaopen_table(Engine);
	luaopen_string(Engine);
	luaopen_math(Engine);

	lua_sethook(Engine, LuaFunction::ExecutionLimit, LUA_MASKCOUNT, 100000);

	int status = luaL_loadfile(Engine, "./util.lua");

	if(status != 0)
	{
		cout << "Error: " << lua_tostring(Engine, -1) << endl;
		return false;
	}
	status = lua_pcall(Engine, 0, LUA_MULTRET, 0);
	if(status != 0)
	{
		cout << "Error: " << lua_tostring(Engine, -1) << endl;
		return false;
	}

	status = luaL_loadfile(Engine, ("."+mExecutionInfo->mRequestInfo->mResource).c_str());

	if(status != 0)
	{
		cout << "Error: " << lua_tostring(Engine, -1) << endl;
		return false;
	}

	// Set up global variables etc.

	lua_newtable(Engine);

	int Top = lua_gettop(Engine);

	for(auto it = mExecutionInfo->mRequestInfo->mHeaders.begin(); it != mExecutionInfo->mRequestInfo->mHeaders.end(); ++it)
	{
		lua_pushstring(Engine, it->first.c_str());
		lua_pushstring(Engine, it->second.c_str());
		lua_settable(Engine, Top);
	}

	lua_setglobal(Engine, "HTTPRequest");

	Luna<CScriptInteraction>::Register(Engine);
	
	Luna<CScriptInteraction>::inject(Engine, mExecutionInfo);
	lua_setglobal(Engine, "HttpObj");

	lua_register(Engine, "dofile", LuaFunction::EmptyFunction);
	lua_register(Engine, "loadfile", LuaFunction::EmptyFunction);
	lua_register(Engine, "load", LuaFunction::EmptyFunction);

	lua_register(Engine, "debugPrint", LuaFunction::OutputToFile);
	return true;
}

bool CLuaAction::ExecuteAction()
{
	RunningScript = true;
	int status = lua_pcall(Engine, 0, LUA_MULTRET, 0);
	if(status == 0)
	{
		RunningScript = false;
		return true;
	}
	else
	{
		RunningScript = false;
		cout << "Error: " << lua_tostring(Engine, -1) << endl;
		return false;
	}
	
}
bool CLuaAction::CleanUp()	
{
	lua_close(Engine);
	return true;
}